package model.bloque;

import model.registro.ConversionesTiposDatos;

public class Bloque {
	
	private int aIdBloque;				//ID del bloque.
	private int aTamanioBloque=0;		//Tamanio del bloque en bytes.
	private int aOffSetBloque=0;		//Posicion del ByteArray donde se encuentra el primer byte libre del bloque.
	private int aEspacioLibre=0;		//Cantidad de bytes libres en el bloque. 
	private int aProximoRegistro=0;		//Posicion del ByteArray donde se encuentra el primer byte del proximo registro a leer.
	
	private byte[] aDatosBloque;		//Datos del bloque.
	
	//El tamanio del bloque debe ser mayor a 4*sizeof(int)
	public Bloque(int xTamanioBloque) {
		aTamanioBloque=xTamanioBloque;
		aEspacioLibre=(xTamanioBloque-(4*ConversionesTiposDatos.sizeOfInt()));
		aOffSetBloque=0;
		aProximoRegistro=0;
		
		aDatosBloque = new byte[aEspacioLibre];		
	}	
	
	//El tamanio del bloque debe ser mayor a 4*sizeof(int)
	public Bloque(int xIdBloque, int xTamanioBloque) {
		aIdBloque=xIdBloque;
		aTamanioBloque=xTamanioBloque;
		aEspacioLibre=(xTamanioBloque-(4*ConversionesTiposDatos.sizeOfInt()));
		aOffSetBloque=0;
		aProximoRegistro=0;
		
		aDatosBloque = new byte[aEspacioLibre];		
	}
	
	public byte[] convertirBloqueABytes() {
				
		int i=0;
		int j=0;

		byte[] bytesIdBloque=new byte[ConversionesTiposDatos.sizeOfInt()];
		byte[] bytesTamanioBloque=new byte[ConversionesTiposDatos.sizeOfInt()];
		byte[] bytesOffSetBloque=new byte[ConversionesTiposDatos.sizeOfInt()];
		byte[] bytesEspacioLibre=new byte[ConversionesTiposDatos.sizeOfInt()];
		
		byte[] bytesBloque=new byte[aTamanioBloque];
		
		
		bytesIdBloque=ConversionesTiposDatos.convertirIntABytes(aIdBloque);
		bytesTamanioBloque=ConversionesTiposDatos.convertirIntABytes(aTamanioBloque);
		bytesOffSetBloque=ConversionesTiposDatos.convertirIntABytes(aOffSetBloque);
		bytesEspacioLibre=ConversionesTiposDatos.convertirIntABytes(aEspacioLibre);
		
		for (i=0; i<ConversionesTiposDatos.sizeOfInt(); i++)
			 bytesBloque[i]=bytesIdBloque[i];
				
		for (j=0; j<ConversionesTiposDatos.sizeOfInt(); j++) {
			bytesBloque[i]=bytesTamanioBloque[j];
			i++;
		}
			
		for (j=0; j<ConversionesTiposDatos.sizeOfInt(); j++) {
			bytesBloque[i]=bytesOffSetBloque[j];
			i++;
		}
			
		for (j=0; j<ConversionesTiposDatos.sizeOfInt(); j++) {
			bytesBloque[i]=bytesEspacioLibre[j];
			i++;
		}
		
		for (j=0; j<(aDatosBloque.length-aEspacioLibre); j++) {
			bytesBloque[i]=aDatosBloque[j];
			i++;
		}

		for (j=0; j<aEspacioLibre; j++) {
			bytesBloque[i]=0;
			i++;
		}
		
		return bytesBloque;		
	}

	
	public void convertirBytesABloque(byte[] xBytesAConvertir) {

		byte[] bytesIdBloque=new byte[ConversionesTiposDatos.sizeOfInt()];		
		byte[] bytesTamanioBloque=new byte[ConversionesTiposDatos.sizeOfInt()];
		byte[] bytesOffSetBloque=new byte[ConversionesTiposDatos.sizeOfInt()];
		byte[] bytesEspacioLibre=new byte[ConversionesTiposDatos.sizeOfInt()];
		
		int i=0;
		int j=0;
		
		for (i=0; i<ConversionesTiposDatos.sizeOfInt(); i++)
			bytesIdBloque[i]=xBytesAConvertir[i];
		
		for (j=0; j<ConversionesTiposDatos.sizeOfInt(); j++) {
			bytesTamanioBloque[j]=xBytesAConvertir[i];
			i++;
		}
		
		for (j=0; j<ConversionesTiposDatos.sizeOfInt(); j++) {
			bytesOffSetBloque[j]=xBytesAConvertir[i];
			i++;
		}
		
		for (j=0; j<ConversionesTiposDatos.sizeOfInt(); j++) {
			bytesEspacioLibre[j]=xBytesAConvertir[i];
			i++;
		}
		
		aIdBloque=ConversionesTiposDatos.convertirBytesAInt(bytesIdBloque);
		aTamanioBloque=ConversionesTiposDatos.convertirBytesAInt(bytesTamanioBloque);
		aOffSetBloque=ConversionesTiposDatos.convertirBytesAInt(bytesOffSetBloque);
		aEspacioLibre=ConversionesTiposDatos.convertirBytesAInt(bytesEspacioLibre);
	
		for (j=0; j<(xBytesAConvertir.length-(4*ConversionesTiposDatos.sizeOfInt())); j++) {
			aDatosBloque[j]=xBytesAConvertir[i];
			i++;
		}
		
	}
	
	public int agregarRegistroABloque(byte[] xBytesAAgregar) {
	
		if ((ConversionesTiposDatos.sizeOfInt()+xBytesAAgregar.length)>aTamanioBloque)
			return -1;
		
		if ((ConversionesTiposDatos.sizeOfInt()+xBytesAAgregar.length)>aEspacioLibre)
			return -2;
		
		
		byte[] bytesLongitudRegistro=new byte[ConversionesTiposDatos.sizeOfInt()];
		bytesLongitudRegistro=ConversionesTiposDatos.convertirIntABytes(xBytesAAgregar.length);
		aEspacioLibre-=(ConversionesTiposDatos.sizeOfInt()+xBytesAAgregar.length);

		for (int i=0; i<(ConversionesTiposDatos.sizeOfInt()+xBytesAAgregar.length); i++) {

			if ((i>=0) && (i<=3))
				aDatosBloque[aOffSetBloque]=bytesLongitudRegistro[i];
			else
				aDatosBloque[aOffSetBloque]=xBytesAAgregar[i-ConversionesTiposDatos.sizeOfInt()];
			
			aOffSetBloque++;
		}
		
		return 0;
	}
	
	public void actualizarRegistro(int xOffSetRegistro, byte[] xBytesAEscribir) {
		
		xOffSetRegistro+=ConversionesTiposDatos.sizeOfInt();
		for (int i=0; i<xBytesAEscribir.length; i++) {
			aDatosBloque[xOffSetRegistro]=xBytesAEscribir[i];
			xOffSetRegistro++;		
		}		
	}
	
	public byte[] getProximoRegistro() {
		
		byte[] bytesDatosRegistro = new byte[0];
		
		if (aProximoRegistro>((aDatosBloque.length)-1))
			return bytesDatosRegistro;
		
		if (((aDatosBloque.length-1)-aProximoRegistro)<(ConversionesTiposDatos.sizeOfInt()+1))
			return bytesDatosRegistro;

		int longitudRegistro=0;
		byte[] bytesLongitudRegistro = new byte[ConversionesTiposDatos.sizeOfInt()];
		for (int i=0; i<ConversionesTiposDatos.sizeOfInt();i++) {
			bytesLongitudRegistro[i]=aDatosBloque[aProximoRegistro];
			aProximoRegistro++;
		}
		
		longitudRegistro=ConversionesTiposDatos.convertirBytesAInt(bytesLongitudRegistro);
		if (longitudRegistro>0) {
			bytesDatosRegistro = new byte[longitudRegistro];

			for (int i=0; i<bytesDatosRegistro.length; i++) {
				bytesDatosRegistro[i]=aDatosBloque[aProximoRegistro];
				aProximoRegistro++;
			}			
		}
		
		return bytesDatosRegistro;		
	}
	
	public void rwBloque() {
		aProximoRegistro=0;
	}
	
	public void resetBloque() {

		aEspacioLibre=(aTamanioBloque-(4*ConversionesTiposDatos.sizeOfInt()));
		aOffSetBloque=0;
		aProximoRegistro=0;
		
		aDatosBloque = new byte[aEspacioLibre];		
		
	}
	
	public int getOffSetProxmimoRegistro() {
		return aProximoRegistro;
	}

	public byte[] getDatosBloque() {
		return aDatosBloque;
	}
	
	public int getTamanio() {
		return aTamanioBloque;
	}
	
	public int getEspacioLibre() {
		return aEspacioLibre;
	}
	
	public int getIdBloque() {
		return aIdBloque;
	}
		
}
